package com.tabjin.rfidsocket.authority.filter;

import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.tabjin.rfidsocket.common.ApplicationContextHelper;
import com.tabjin.rfidsocket.common.RequestHolder;
import com.tabjin.rfidsocket.common.utils.JsonMapper;
import com.tabjin.rfidsocket.common.utils.TabJsonResult;
import com.tabjin.rfidsocket.pojo.vo.SysUserVO;
import com.tabjin.rfidsocket.service.sys.SysCoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author tabjin
 * create at 2020/12/30 00:18
 * @program rfid_socket
 * @description
 */
//@Order(2)
//@WebFilter(filterName = "globalAclControlFilter",
//        urlPatterns = {"/sys/*", "/admin/*", "/access/*"},
//        initParams = {@WebInitParam(name = "targetFilterLifecycle", value = "true"), @WebInitParam(name = "exclusionUrls", value = "/sys/user/noAuth.page,/login.page")},
//        description = "权限拦截器，拦截url要小于等于LoginFilter")
public class GlobalAclControlFilter implements Filter {

    static final Logger logger = LoggerFactory.getLogger(GlobalAclControlFilter.class);

    private static final String NOAUTHURL = "/sys/user/noAuth";

    private static Set<String> exclusionUrlSet = Sets.newConcurrentHashSet();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("GlobalAclControlFilter init");
        // 相当于读取配置文件中的指定字段
        String exclusionUrls = filterConfig.getInitParameter("exclusionUrls");
        List<String> exclusionUrlList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(exclusionUrls);
        exclusionUrlSet = Sets.newConcurrentHashSet(exclusionUrlList);// 白名单
        exclusionUrlSet.add(NOAUTHURL);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String servletPath = httpServletRequest.getServletPath();// 当前请求url
        Map requestMap = httpServletRequest.getParameterMap();

        if (exclusionUrlSet.contains(servletPath)) {// 请求在白名单中，直接过滤链出去，不需拦截
            chain.doFilter(request, response);
            return;
        }

        // 权限校验必须保证走过LoginFilter，LoginFilter不过都走不到这边
        SysUserVO currentUser = RequestHolder.getCurrentUser();
        // 无权限访问
        if (currentUser == null) {
            logger.info("someone visit {} , but no login! parameter: {}", servletPath, JsonMapper.obj2String(requestMap));
            noAuth(httpServletRequest, httpServletResponse);
            return;
        }

        // 由于Filter不是Spring管理的，需要从ApplicationContext取值
        SysCoreService sysCoreService = ApplicationContextHelper.popBean(SysCoreService.class);// 取出被Spring管理的bean
        // 判断某个用户是否可以访问某个url
        boolean a = sysCoreService.hasUrlAcl(servletPath);
        if (!sysCoreService.hasUrlAcl(servletPath)) {
            logger.info("{} visit {} , but no login! parameter: {}", JsonMapper.obj2String(currentUser), servletPath, JsonMapper.obj2String(requestMap));
            noAuth(httpServletRequest, httpServletResponse);// 进入无权限访问
            return;
        }
        chain.doFilter(request, response);
        return;
    }

    @Override
    public void destroy() {

    }

    /**
     * 无权限
     *
     * @param httpServletRequest
     * @param httpServletResponse
     */
    private void noAuth(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
        String servletPath = httpServletRequest.getServletPath();
        // json请求 or page请求
        if (servletPath.endsWith(".json")) {
            TabJsonResult jsonResult = TabJsonResult.errorMessage("没有访问权限！");
            httpServletResponse.setHeader("Content-Type", "application/json");
            httpServletResponse.getWriter().print(JsonMapper.obj2String(jsonResult));
            return;
        } else {
            clientRedirect(NOAUTHURL, httpServletResponse);
            return;
        }
    }

    /**
     * 重定向
     *
     * @param url
     * @param httpServletResponse
     */
    private void clientRedirect(String url, HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.setHeader("Content-Type", "text/html");
        // 跳转逻辑
        httpServletResponse.getWriter().print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"/>\n"
                + "<title>跳转中...</title>\n" + "</head>\n" + "<body>\n" + "跳转中，请稍候...\n" + "<script type=\"text/javascript\">//<![CDATA[\n"
                + "window.location.href='" + url + "?ret='+encodeURIComponent(window.location.href);\n" + "//]]></script>\n" + "</body>\n" + "</html>\n");
    }
}
